package cn.aws360.boot.wechat.biz.service.impl;

import cn.aws360.boot.base.api.constant.enums.DelFlagEnum;
import cn.aws360.boot.base.api.exception.ServiceException;
import cn.aws360.boot.data.api.constant.DataConstant;
import cn.aws360.boot.data.api.factory.PageFactory;
import cn.aws360.boot.data.api.pojo.request.PageQuery;
import cn.aws360.boot.data.api.pojo.response.PageResult;
import cn.aws360.boot.data.api.utils.PojoUtils;
import cn.aws360.boot.wechat.api.constant.WxmConstant;
import cn.aws360.boot.wechat.api.exception.WxmExceptionEnum;
import cn.aws360.boot.wechat.api.pojo.request.WxmAppQuery;
import cn.aws360.boot.wechat.api.pojo.request.WxmAppWrite;
import cn.aws360.boot.wechat.api.pojo.response.WxmAppModel;
import cn.aws360.boot.wechat.biz.domain.WxmApp;
import cn.aws360.boot.wechat.biz.mapper.WxmAppMapper;
import cn.aws360.boot.wechat.biz.service.WxmAppService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author junnan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WxmAppServiceImpl extends ServiceImpl<WxmAppMapper, WxmApp> implements WxmAppService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = WxmConstant.MODULE_WXM_APP_CACHE, allEntries = true)
    public Boolean add(WxmAppWrite wxmAppWrite) {
        WxmApp wxmApp = BeanUtil.copyProperties(wxmAppWrite, WxmApp.class, DataConstant.ID);
        checkAppIdHasExist(wxmApp);
        return this.save(wxmApp);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = WxmConstant.MODULE_WXM_APP_CACHE, allEntries = true)
    public Boolean edit(WxmAppWrite wxmAppWrite) {
        WxmApp wxmApp = this.getWxAppById(wxmAppWrite.getId());
        BeanUtil.copyProperties(wxmAppWrite, wxmApp);
        checkAppIdHasExist(wxmApp);
        return this.updateById(wxmApp);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = WxmConstant.MODULE_WXM_APP_CACHE, allEntries = true)
    public Boolean remove(String ids) {
        List<Integer> appIdList = Convert.toList(Integer.class, ids.split(StrUtil.COMMA));
        return this.removeByIds(appIdList);
    }

    @Override
    public WxmAppModel detail(Integer id) {
        WxmApp wxmApp = this.getWxAppById(id);
        return BeanUtil.copyProperties(wxmApp, WxmAppModel.class);
    }

    @Override
    public List<WxmAppModel> findList(WxmAppQuery wxmAppQuery) {
        LambdaQueryWrapper<WxmApp> queryWrapper = createQueryWrapper(wxmAppQuery);
        List<WxmApp> wxmAppList = this.list(queryWrapper);
        return PojoUtils.copyToList(wxmAppList, WxmAppModel.class);
    }

    @Override
    public PageResult<WxmAppModel> findPage(WxmAppQuery wxmAppQuery, PageQuery pageQuery) {
        LambdaQueryWrapper<WxmApp> queryWrapper = createQueryWrapper(wxmAppQuery);
        PageResult<WxmApp> wxAppPage = PageFactory.getPageResult(this, pageQuery, queryWrapper);
        return PojoUtils.copyToPage(wxAppPage, WxmAppModel.class);
    }

    private WxmApp getWxAppById(Integer id) {
        WxmApp wxmApp = this.getById(id);
        checkNotExist(wxmApp);
        return wxmApp;
    }

    private LambdaQueryWrapper<WxmApp> createQueryWrapper(WxmAppQuery wxmAppQuery) {
        return Wrappers.<WxmApp>lambdaQuery()
                .eq(ObjectUtil.isNotNull(wxmAppQuery.getType()), WxmApp::getType, wxmAppQuery.getType())
                .eq(StrUtil.isNotBlank(wxmAppQuery.getAppId()), WxmApp::getAppId, wxmAppQuery.getAppId())
                .like(StrUtil.isNotBlank(wxmAppQuery.getAppName()), WxmApp::getAppName, wxmAppQuery.getAppName())
                .orderByAsc(WxmApp::getId);
    }

    private void checkNotExist(WxmApp wxmApp) {
        if (ObjectUtil.isNull(wxmApp) || DelFlagEnum.Y.getValue().equals(wxmApp.getDelFlag())) {
            throw new ServiceException(WxmExceptionEnum.WXM_APP_NOT_EXIST);
        }
    }

    private void checkAppIdHasExist(WxmApp wxmApp) {
        Integer id = wxmApp.getId();
        String appId = wxmApp.getAppId();
        id = (ObjectUtil.isNotNull(id) && id != 0) ? id : -1;
        WxmApp existWxmApp = this.getOne(Wrappers.<WxmApp>lambdaQuery().eq(WxmApp::getAppId, appId));
        if (ObjectUtil.isNotNull(existWxmApp) && !existWxmApp.getId().equals(id)) {
            throw new ServiceException(WxmExceptionEnum.WXM_APP_ID_HAS_EXIST, appId);
        }
    }

}
